//引入必要的模块
const express = require("express");
const bodyParser = require("body-parser");
const md5 = require("md5");
const session = require("express-session");
const NedbStore = require('nedb-session-store')(session);
const dao = require("./model/dao.js");
//初始化功能
const ip = "192.168.1.101";
const port = "8989";
const userList = {};
const app = express();
const urlencodedParser = bodyParser.urlencoded({
	extended: false
});
const dbName = "weibo";
const colName = "userinfo";
const msgName = "msglist";
const chatName = "chatlist";
// 配置socket.io
const http = require('http').Server(app);
const io = require('socket.io')(http);
// 配置ejs
const ejs = require('ejs');
app.set('view engine', 'ejs');
//设置配置session并设置持久化
app.use(session({
	secret: "key secret weibo",
	resave: false,
	saveUninitialized: true,
	cookie: {
		maxAge: 1800000
	},
	store: new NedbStore({
		filename: "nedbStore.db"
	})
}));
//处理静态资源
app.use("/public", express.static("./public/"));
//处理页面跳转
app.get("/", (req, res) => {
	logreg(req, res, {
		title: "登录",
		href: `没有账号？<a href="reg">点击注册</a>`,
		ajax: "login"
	})
});
app.get("/login", (req, res) => {
	logreg(req, res, {
		title: "登录",
		href: `没有账号？<a href="reg">点击注册</a>`,
		ajax: "login"
	})
});
//跳转注册页面
app.get("/reg", (req, res) => {
	logreg(req, res, {
		title: "注册",
		href: `已有账号？<a href="/">点击登录</a>`,
		ajax: "reg"
	})
});

function logreg(req, res, obj) {
	obj.url = `${ip}:${port}`;
	let user = req.session.user;
	if (user) {
		dao.find(dbName, colName, function(result) {
			if (result.length == 1) {
				req.session.user = user;
				res.render('chat', {
					user: user,
					token: req.session.token,
					ajax: "logout",
					url: `${ip}:${port}`
				})
			} else {
				res.render('login', obj)
			}
		}, {
			user: user
		}, 1);
	} else {
		res.render('login', obj)
	}
}
//退出登录
app.get("/logout", (req, res) => {
	req.session.user = null;
	req.session.token = null;
	res.send({
		code: 1
	})
})
//处理登录信息
app.post("/login", urlencodedParser, (req, res) => {
	dealWith(req, res, (user, pass, result) => {
		if (result.length == 1) {
			if (result[0].pass == md5(md5(pass))) {
				req.session.user = user;
				req.session.token = md5(md5(`u-${user},p-${pass},t-${new Date().getTime()},s-weibo`));
				dao.update(dbName, colName, function(result) {
					if (result.result.ok == 1) {
						res.send({
							code: 1
						})
					} else {
						res.send({
							code: -7
						})
					}
				}, {
					user: user
				}, {
					$set: {
						token: req.session.token
					}
				})
			} else {
				res.send({
					code: -6
				})
			}
		} else {
			res.send({
				code: -5
			})
		}
	});
})
//处理注册信息
app.post("/reg", urlencodedParser, (req, res) => {
	dealWith(req, res, (user, pass, result) => {
		if (result.length == 1) {
			res.send({
				code: -5
			})
		} else {
			dao.insert(dbName, colName, function(result) {
				if (result.result.ok == 1) {
					res.send({
						code: 1
					})
				} else {
					res.send({
						code: -6
					})
				}
			}, {
				user: user,
				pass: md5(md5(pass)),
				token: "",
				date: new Date().getTime()
			})
		}
	})
})

function dealWith(req, res, call) {
	let user = req.body.user;
	let pass = req.body.pass;
	if (user == "") {
		res.send({
			code: -1
		});
	} else if (!user.match(/[_a-zA-Z0-9]{5,13}/)) {
		res.send({
			code: -2
		});
	} else {
		if (pass == "") {
			res.send({
				code: -3
			});
		} else if (!pass.match(/[a-zA-Z0-9]{6,20}/)) {
			res.send({
				code: -4
			});
		} else {
			dao.find(dbName, colName, function(result) {
				call(user, pass, result);
			}, {
				user: user
			}, 1);

		}
	}
}
//配置长连接
io.on('connection', function(socket) {
	let user = "";
	let token = "";
	let num = 0;
	socket.on('new', function(info) {
		//判断信息是否有效
		if (info.user && info.token) {
			console.log(`[${info.user}]试图进入聊天室`);
			//判断当前连接是否已登录
			if (user != "") {
				if (info.user == user) {
					send_info(socket, -2, "你已登录，请不要重复登录");
				} else {
					send_info(socket, -3, "你已登录，请退出后再切换其他账号");
				}
			} else {
				//判断当前要登录的账号是否已登录
				let exits = userList.hasOwnProperty(info.user);
				if (exits) { //若已登录，做提醒
					send_info(userList[info.user].socket, -4, "当前账号正在试图从其他地方登录");
				}
				dao.find(dbName, colName, function(result) {
					if (result.length == 1) {
						if (result[0].token == info.token) {
							console.log(`[${info.user}]成功进入聊天室`);
							if (exits) {
								console.log(`[${info.user}]从其他地方登录`);
								send_info(userList[info.user].socket, -8, "当前账号已从其他地方登录");
								userList[info.user].exit = true;
							}else{
								userList[info.user] = {socket:null,exit:false};
							}
							user = info.user;
							token = info.token;
							userList[user].socket = socket;
							io.emit("join", {
								name: user
							});
							socket.emit("list", {
								list: Object.keys(userList)
							})
						} else {
							console.log(`[${info.user}]登录凭证错误`);
							send_info(socket, -5, "登录凭证错误");
							if (++num == 3) {
								socket.close();
							}
						}
					} else {
						console.log(`[${info.user}]未注册，已断开`);
						socket.close();
					}
				}, {
					user: info.user
				}, 1);
			}
		} else {
			send_info(socket, -1, "信息无效");
			if (++num == 3) {
				socket.close();
			}
		}
	})
	socket.on('chat', function(info) {
		//socket.emit("chat", data);
		if (user != "") {
			if (info.msg) {
				io.emit('chat', {
					name: user,
					msg: info.msg,
					time: new Date().getTime()
				});
			} else {
				send_info(socket, -6, "请输入消息内容");
			}
		} else {
			send_info(socket, -7, "请先登录");
		}
	});
	socket.on('disconnect', function() {
		if (user != "") {
			console.log(`[${user}]离开了聊天室`);
			io.emit("exit", {
				name: user
			});
			if (!userList[user].exit) {
				delete userList[user];
			}
		}
	})
})
//发送提示消息
function send_info(socket, code, msg) {
	socket.emit("info", {
		code: code,
		msg: msg
	})
}
//监听端口
http.listen(port, ip);
